#include "mq_channel.hpp"

namespace zdfmq
{
    /**
     * @brief 连接类，管理单个TCP连接上的所有信道（Channel）
     * 每个TCP连接对应一个Connection实例，负责信道的创建、关闭和查找
     */
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>; // 智能指针类型别名

        /**
         * @brief 构造函数
         * @param host 所属虚拟主机
         * @param cmp 消费者管理器
         * @param codec Protobuf编解码器
         * @param conn 底层TCP连接
         * @param pool 线程池（用于异步任务）
         */
        Connection(const VirtualHost::ptr &host,
                   const ConsumerManager::ptr &cmp,
                   const ProtobufCodecPtr &codec,
                   const muduo::net::TcpConnectionPtr &conn,
                   const threadpool::ptr &pool) : _conn(conn),                                  // 绑定TCP连接
                                                  _codec(codec),                                // 绑定编解码器
                                                  _cmp(cmp),                                    // 绑定消费者管理器
                                                  _host(host),                                  // 绑定虚拟主机
                                                  _pool(pool),                                  // 绑定线程池
                                                  _channels(std::make_shared<ChannelManager>()) // 初始化信道管理器
        {
        }

        /**
         * @brief 打开新信道
         * @param req 打开信道的请求（包含信道ID等信息）
         * 流程：调用信道管理器创建信道，返回操作结果
         */
        void openChannel(const openChannelRequestPtr &req)
        {
            // 1. 调用信道管理器创建信道，判断是否成功（信道ID是否重复）
            bool ret = _channels->openChannel(
                req->cid(), // 信道ID
                _host,      // 虚拟主机
                _cmp,       // 消费者管理器
                _codec,     // 编解码器
                _conn,      // TCP连接
                _pool       // 线程池
            );

            if (ret == false)
            { // 创建失败（ID重复）
                DLOG("创建信道的时候，信道ID重复了");
                return basicResponse(false, req->rid(), req->cid());
            }

            DLOG("%s 信道创建成功！", req->cid().c_str());
            // 2. 向客户端返回成功响应
            return basicResponse(true, req->rid(), req->cid());
        }

        /**
         * @brief 关闭信道
         * @param req 关闭信道的请求（包含信道ID）
         * 流程：调用信道管理器移除指定信道，返回成功响应
         */
        void closeChannel(const closeChannelRequestPtr &req)
        {
            _channels->closeChannel(req->cid()); // 移除信道
            return basicResponse(true, req->rid(), req->cid());
        }

        /**
         * @brief 获取指定ID的信道
         * @param cid 信道ID
         * @return 信道智能指针（不存在则返回空）
         */
        Channel::ptr getChannel(const std::string &cid)
        {
            return _channels->getChannel(cid);
        }

    private:
        /**
         * @brief 向客户端发送基础响应
         * @param ok 操作结果（成功/失败）
         * @param rid 请求ID（用于匹配请求与响应）
         * @param cid 信道ID
         */
        void basicResponse(bool ok, const std::string &rid, const std::string &cid)
        {
            basicCommonResponse resp;
            resp.set_rid(rid);         // 请求ID
            resp.set_cid(cid);         // 信道ID
            resp.set_ok(ok);           // 操作结果
            _codec->send(_conn, resp); // 通过TCP连接发送响应
        }

    private:
        muduo::net::TcpConnectionPtr _conn; // 底层TCP连接
        ProtobufCodecPtr _codec;            // Protobuf编解码器
        ConsumerManager::ptr _cmp;          // 消费者管理器
        VirtualHost::ptr _host;             // 所属虚拟主机
        threadpool::ptr _pool;              // 线程池
        ChannelManager::ptr _channels;      // 信道管理器（管理当前连接上的所有信道）
    };

    /**
     * @brief 连接管理器，管理服务器上的所有Connection实例
     * 负责TCP连接的创建、销毁和查找，保证线程安全
     */
    class ConnectionManager
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>; // 智能指针类型别名

        ConnectionManager() {} // 构造函数

        /**
         * @brief 创建新连接（当客户端建立TCP连接时调用）
         * @param host 虚拟主机
         * @param cmp 消费者管理器
         * @param codec 编解码器
         * @param conn TCP连接
         * @param pool 线程池
         */
        void newConnection(const VirtualHost::ptr &host,
                           const ConsumerManager::ptr &cmp,
                           const ProtobufCodecPtr &codec,
                           const muduo::net::TcpConnectionPtr &conn,
                           const threadpool::ptr &pool)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁保证线程安全
            auto it = _conns.find(conn);
            if (it != _conns.end())
            { // 连接已存在，直接返回
                return;
            }
            // 创建新Connection并加入管理
            Connection::ptr self_conn = std::make_shared<Connection>(host, cmp, codec, conn, pool);
            _conns.insert(std::make_pair(conn, self_conn));
        }

        /**
         * @brief 销毁连接（当TCP连接断开时调用）
         * @param conn 要销毁的TCP连接
         */
        void delConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁保证线程安全
            _conns.erase(conn);                        // 移除连接
        }

        /**
         * @brief 获取TCP连接对应的Connection实例
         * @param conn TCP连接
         * @return Connection智能指针（不存在则返回空）
         */
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁保证线程安全
            auto it = _conns.find(conn);
            if (it == _conns.end())
            { // 连接不存在
                return Connection::ptr();
            }
            return it->second;
        }

    private:
        std::mutex _mutex; // 线程安全锁（保护连接映射表）
        // 连接映射表：key为TCP连接，value为对应的Connection实例
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
    };
}